﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using AzukiMap.MapSource;
using AzukiMap.Map;
using AzukiMap.Tools.Logger;
using Geotools.Geometries;
using AzukiMap.Tools;

namespace AzukiMap.Layer
{
    public class RasterLayer : Layer
    {
        protected double _bufferWidth;
        protected double _bufferHeight;
        protected RasterSource _rasterMapSource;

        public double BufferWidth
        {
            get { return _bufferWidth; }
            set { _bufferWidth = value; }
        }

        public double BufferHeight
        {
            get { return _bufferHeight; }
            set { _bufferHeight = value; }
        }

        public RasterSource MapSource
        {
            get { return _rasterMapSource; }
        }

        public GTPolygon MapExtent
        {
            get { return _maxExtent; }
        }

        public RasterLayer(RasterSource rasterMapSource, MapCanvas mapCanvas, string name) 
            : base(mapCanvas, rasterMapSource.Type, rasterMapSource)
        {
            Init(rasterMapSource, name, _geoUtil.EnvelopeToPolygon(rasterMapSource.MaxExtent));
        }

        public RasterLayer(RasterSource rasterMapSource, MapCanvas mapCanvas, string name, GTPolygon mapExtent) 
            : base(mapCanvas, rasterMapSource.Type, rasterMapSource)
        {
            Init(rasterMapSource, name, mapExtent);
        }

        void Init(RasterSource rasterMapSource, string name, GTPolygon maxExtent)
        {
            _rasterMapSource = rasterMapSource;
            _name = name;
            _maxExtent = maxExtent;
            _geoUtil = new GeometryUtil();
            _maxScale = rasterMapSource.MaxScale;
            _minScale = rasterMapSource.MinScale;
        }

        public override void Draw()
        {
            if (!HasExtent() || !CheckMaxExtent() || !CheckScale())
            {
                Logger.Debug("WMSLayer.Draw(): Drawing was skipped.");
                return;
            }
            Image rasterImage = new Image();
            BitmapImage imageSource = new BitmapImage(_rasterMapSource.ImageUri);
            GTPoint origin = GetOrigin();
            
            rasterImage.Source = imageSource;
            rasterImage.Width = GetWidth();
            rasterImage.Height = GetHeight();
            rasterImage.HorizontalAlignment = HorizontalAlignment.Right;
            rasterImage.VerticalAlignment = VerticalAlignment.Top;
            rasterImage.RenderTransform = GetImageTransform();

            rasterImage.SetValue(Canvas.LeftProperty, origin.X);
            rasterImage.SetValue(Canvas.TopProperty, origin.Y);
            
            _mapCanvas.Children.Add(rasterImage);
            //_mapCanvas.Children.Add(_rasterMapSource.RasterImage);
        }

        public override void Clear()
        {
            base.Clear();
            _mapCanvas.Children.Clear();
        }

        GTPoint GetOrigin()
        {
            GTCoordinate tlPoint = _geoUtil.GetExtentPoint(_maxExtent, ExtentOrder.TOP_LEFT);
            return _mapCanvas.GetPixPointFromGeo(tlPoint.X, tlPoint.Y);
        }

        double GetWidth()
        {
            //double extentWidth = _geoUtil.GetExtentPolygonWidth(_rasterMapSource.MaxExtent);
            double extentWidth = _rasterMapSource.MaxExtent.Width;
            return extentWidth / _mapCanvas.ScreenScale;
        }

        double GetHeight()
        {
            //double extentHeight = _geoUtil.GetExtentPolygonHeight(_rasterMapSource.MaxExtent);
            double extentHeight = _rasterMapSource.MaxExtent.Height;
            return extentHeight / _mapCanvas.ScreenScale;
        }

        TransformGroup GetImageTransform()
        {
            TransformGroup transGroup = new TransformGroup();
            TranslateTransform moveTransform = new TranslateTransform();
            ScaleTransform scaleTransform = new ScaleTransform();

            //double geoWidth = _geoUtil.GetExtentPolygonWidth(_rasterMapSource.MaxExtent);
            //double geoHeight = _geoUtil.GetExtentPolygonHeight(_rasterMapSource.MaxExtent);
            double geoWidth = _rasterMapSource.MaxExtent.Width;
            double geoHeight = _rasterMapSource.MaxExtent.Height;
            double imgOrgWidth = _rasterMapSource.Width;
            double imgOrgHeight = _rasterMapSource.Height;

            double geoAspectRatio = geoWidth / geoHeight;
            double imgAspectRatio = imgOrgWidth / imgOrgHeight;

            double scaleX = geoAspectRatio / imgAspectRatio;
            double moveX = GetWidth() * (( scaleX - 1 ) / 2) * -1;

            scaleTransform.ScaleX = scaleX;
            moveTransform.X = moveX;

            transGroup.Children.Add(scaleTransform);
            transGroup.Children.Add(moveTransform);

            return transGroup;
        }

        bool HasExtent()
        {
            if (_maxExtent == null)
            {
                return false;
            }
            return (! _maxExtent.IsEmpty());
        }
    }
}
